#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>

#include "lin_al.h"

/*
 * Various functions for managing matrix datatype
 */

void
fprint_matrix(struct matrix *A, FILE* stream)
{
	register int i, j;
	for (i = 0 ; i < A->m ; ++i) {
		for (j = 0 ; j < A->n ; ++j) {
			(void) fprintf(stream, " %7g", A->data[i][j]);
		}
		putc('\n', stream);
	}
}

void
swap_rows(struct matrix* a, int x, int y)
{
	register double tmp;
	int i;
	for (i = 0 ; i < a->n ; ++i) {
		tmp	      = a->data[x][i];
		a->data[x][i] = a->data[y][i];
		a->data[y][i] = tmp;
	}
	a->determinant *= -1;
}

void *
my_malloc(size_t size)
{
	void *ptr;
	if ((ptr = malloc(size)) == NULL) {
		fprintf(stderr, "%s(): failed to alloc %lu bytes\nAborting.\n",
				__func__, size);
		abort();
	}
	return ptr;
}

void *
my_calloc(size_t n, size_t size)
{
	void *ptr;
	if ((ptr = calloc(n, size)) == NULL) {
		fprintf(stderr, "%s(): failed to alloc %lu bytes\nAborting.\n",
				__func__, size);
		abort();
	}
	return ptr;
}

int
matrix_calloc(struct matrix *A)
{
	register int j = 0;
	A->data = my_calloc((size_t) A->m, sizeof(double*));
	while (j < A->m) {
		A->data[j] = my_calloc((size_t) A->n, sizeof(double));
		j++;
	}
	return 0; /* success */
}

/*
 * XXX: This function frees not only the matrix' data but also the matrix
 * pointer itself.
 */
void
matrix_free(struct matrix *A)
{
	register unsigned int j = 0U;
	while (j < A->m)
		free(A->data[j++]);
	free(A->data);
	free(A);
}
